Homework 4
Contents
Chapter 2: Diffraction
5.5. Homework 4#
Analyzing Spot Diffraction Pattern
part of
MSE672: Introduction to Transmission Electron Microscopy
by Gerd Duscher, Spring 2023
Microscopy Facilities
Institute of Advanced Materials & Manufacturing
Materials Science & Engineering
The University of Tennessee, Knoxville
Background and methods to analysis and quantification of data acquired with transmission electron microscopes.
5.5.1. Overview#
This homework follows the notebook: Analyzing Spot Diffraction Pattern
5.5.2. Load relevant python packages#
5.5.2.1. Check Installed Packages#
import sys
from pkg_resources import get_distribution, DistributionNotFound
def test_package(package_name):
"""Test if package exists and returns version or -1"""
try:
version = get_distribution(package_name).version
except (DistributionNotFound, ImportError) as err:
version = '-1'
return version
if test_package('pyTEMlib') < '0.2022.2.3':
print('installing pyTEMlib')
!{sys.executable} -m pip install --upgrade pyTEMlib
print('done')
done
5.5.2.2. Load the plotting and figure packages#
Import the python packages that we will use:
Beside the basic numerical (numpy) and plotting (pylab of matplotlib) libraries,
three dimensional plotting and some libraries from the book
kinematic scattering library.
%pylab notebook
%gui qt
# 3D and selection plotting package
from mpl_toolkits.mplot3d import Axes3D # 3D plotting
from matplotlib.widgets import EllipseSelector
# additional package
import itertools
import scipy.constants as const
import os
# our blob detectors from the scipy image package
from skimage.feature import blob_dog
# Import libraries from the book
import pyTEMlib
import pyTEMlib.kinematic_scattering as ks # Kinematic sCattering Library
# with Atomic form factors from Kirklands book
import pyTEMlib.file_tools as ft
# it is a good idea to show the version numbers at this point for archiving reasons.
__notebook_version__ = '2022.02.18'
print('pyTEM version: ', pyTEMlib.__version__)
print('notebook version: ', __notebook_version__)
Populating the interactive namespace from numpy and matplotlib
Symmetry functions of spglib enabled
Using kinematic_scattering library version {_version_ } by G.Duscher
pyTEM version: 0.2022.2.1
notebook version: 2022.02.10
5.5.3. Load Ring-Diffraction Pattern#
This ho
5.5.3.1. First we select the diffraction pattern#
In the second lab we used a sample of either gold (Tuesday) or Aluminium (Wednesday)
Download your images from the google drive at https://drive.google.com/drive/folders/1TId7PiGUbip8m8JgX2FL5PaNjld1idzt?usp=sharing
You must log into Google with your UTK account to be able to read these data.
Go to the folder of you data and select one
The dynamic range of diffraction patterns is too high for computer screens and so we take the logarithm of the intensity.
# ------Input -------------
load_your_own_data = False
# -------------------------
try:
# close any open files before open new one
main_dataset.h5_dataset.file.close()
except:
pass
if load_your_own_data:
main_dataset = ft.open_file()
else: # load example
main_dataset = ft.open_file(os.path.join("../example_data", "Si001_300mm_alpha0.1_beta9.4_diff.dm3"))
view = main_dataset.plot(vmax=20000)
Cannot overwrite file. Using: Si001_300mm_alpha0.1_beta9.4_diff-3.hf5
C:\Users\gduscher\Anaconda3\lib\site-packages\pyNSID\io\hdf_utils.py:350: FutureWarning: validate_h5_dimension may be removed in a future version
warn('validate_h5_dimension may be removed in a future version',
5.5.4. Finding the center#
5.5.4.1. Select the center yourself#
Select the center of the screen with the ellipse selection tool
## Access the data of the loaded image
radius = 559
diff_pattern = np.array(main_dataset.T)
diff_pattern = diff_pattern-diff_pattern.min()
center = np.array([1024, 1024])
plt.figure(figsize=(8, 6))
plt.imshow(np.log(3.+diff_pattern), origin = 'upper')
current_axis = plt.gca()
selector = EllipseSelector(current_axis, None,interactive=True , drawtype='box') # gca get current axis (plot)
selector.to_draw.set_visible(True)
center = np.array(center)
selector.extents = (center[0]-radius,center[0]+radius,center[1]-radius,center[1]+radius)
Get center coordinates from selection
xmin, xmax, ymin, ymax = selector.extents
x_center, y_center = selector.center
x_shift = x_center - diff_pattern.shape[0]/2
y_shift = y_center - diff_pattern.shape[1]/2
print(f'radius = {(xmax-xmin)/2:.0f} pixels')
center = (x_center, y_center )
print(f'center = {center} [pixels]')
out_tags ={}
out_tags['center'] = center
radius = 559 pixels
center = (1112.6580086580084, 1055.030303030303) [pixels]
5.5.5. Determine Bragg Peaks#
Peak finding is actually not as simple as it looks
# The beam stop is rather dark
beam_stop = np.argwhere(diff_pattern.T < 100)
# Determine all spots
dif = np.log2(1+diff_pattern)
dif = dif-dif.min() # blog detector does not like negative values
spots = blob_dog(dif.T, max_sigma=12, threshold=.9)
Bragg_spots = []
# We only consider spots not associated with the beam stop (which confuses the blob finder)
for spot in spots:
if np.min(np.linalg.norm(beam_stop-spot[:2], axis=1))> 100:
Bragg_spots.append(spot[0:2])
Bragg_spots = np.array(Bragg_spots)
Bragg_spots = Bragg_spots[np.argsort(np.linalg.norm(Bragg_spots[:,:2]-center, axis=1)),:]
plt.figure()
plt.imshow(np.log2(1+diff_pattern),cmap="gray", vmin=np.max(np.log2(1+diff_pattern))*0.5)
plt.scatter(Bragg_spots[:,0], Bragg_spots[:,1], c='green', alpha = 0.5)
<matplotlib.collections.PathCollection at 0x1e702f65550>
5.5.5.1. Refine Center#
We use the N innermost reflections and the average of those positions is the new center
Please choose the max_distance value so that you have a symmetric selection of Bragg spots around the center
# ----- Input -------------
max_distance = 600 # pixel
# -------------------------
close_spots = Bragg_spots[np.linalg.norm(Bragg_spots[:,:2]-center[:2], axis=1) <max_distance]
refined_center = np.average(close_spots, axis=0)
close_spots -= refined_center
spots_experiment = (Bragg_spots-refined_center)
fig = plt.figure()
extent= np.array([-refined_center[0], diff_pattern.shape[0]-refined_center[0],
diff_pattern.shape[1]-refined_center[1], -refined_center[1]])
plt.imshow(np.log2(1+diff_pattern), cmap="gray", extent=extent, vmin=np.max(np.log2(1 + diff_pattern)) * 0.5)
plt.scatter(spots_experiment[:,0], spots_experiment[:,1], c='green', alpha = 0.5,
label='spots')
plt.scatter(close_spots[:,0], close_spots[:,1], c='orange', alpha = 0.5,
label='close spots')
plt.xlabel('reciprocal distance [1/$\AA$]')
plt.scatter(0, 0, color='red')
<matplotlib.collections.PathCollection at 0x1e702fe59a0>
5.5.6. Calculate Spot Pattern#
see Plotting of Diffraction Pattern for details
# -------Input -----
material = 'silicon'
zone_hkl = [0,0,1]
# -------------------
atoms = ks.structure_by_name(material)
atoms.info['experimental']={}
### Define experimental parameters:
atoms.info['experimental']['acceleration_voltage_V'] = 200.0 *1000.0 #V
atoms.info['experimental']['new_figure'] = False
atoms.info['experimental']['plot FOV'] = 3 # in 1/Ang
atoms.info['experimental']['convergence_angle_mrad'] = 0
atoms.info['experimental']['zone_hkl'] = np.array(zone_hkl) # incident nearest zone axis: defines Laue Zones!!!!
atoms.info['experimental']['mistilt'] = np.array([0,0,0]) # mistilt in degrees
atoms.info['experimental']['Sg_max'] = .04 # 1/Ang maximum allowed excitation error ; This parameter is related to the thickness
atoms.info['experimental']['hkl_max'] = 15 # Highest evaluated Miller indices
######################################
# Diffraction Simulation of Crystal #
######################################
d = ks.kinematic_scattering(atoms, verbose = True)
reciprocal_unit_cell
[[0.184 0. 0. ]
[0. 0.184 0. ]
[0. 0. 0.184]]
The inner potential is 46.5V
Using an acceleration voltage of 200.0kV
Magnitude of incident wave vector in material: 40.5 1/Ang and in vacuum: 39.9 1/Ang
Which is an wave length of 2.472 pm in the material and 2.508 pm in the vacuum
The convergence angle of 0.0mrad = 0.00 1/A
Magnitude of incident wave vector in material: 40.5 1/A which is a wavelength 2.472 pm
Rotation alpha 0.0 degree, beta 0.0 degree
from zone axis [0 0 1]
Tilting 1 by 0.00 in alpha and 0.00 in beta direction results in :
Next nearest zone axes are:
Center of Ewald sphere [ 0. 0. 40.45252569]
Of the 29790 tested reciprocal_unit_cell points, 340 have an excitation error less than 0.04 1/Angstrom
Of the 340 possible reflection 56 are allowed.
Laue_circle [0. 0. 0.]
There are 36 allowed reflections in the zero order Laue Zone
There are 20 allowed reflections in the first order Laue Zone
There are 0 allowed reflections in the second order Laue Zone
There are 0 allowed reflections in the higher order Laue Zone
hkl Laue zone Intensity (*1 and log) length
[-15. -15. 1.] [-2.76198332 -2.76198332 0.18413222] 0.101 0.097 3.910
[-15. -13. 1.] [-2.76198332 -2.39371888 0.18413222] 0.131 0.123 3.660
[-15. -11. 1.] [-2.76198332 -2.02545444 0.18413222] 0.168 0.155 3.430
[-15. 11. 1.] [-2.76198332 2.02545444 0.18413222] 0.168 0.155 3.430
[-15. 13. 1.] [-2.76198332 2.39371888 0.18413222] 0.131 0.123 3.660
[-15. 15. 1.] [-2.76198332 2.76198332 0.18413222] 0.101 0.097 3.910
[-13. -15. 1.] [-2.39371888 -2.76198332 0.18413222] 0.131 0.123 3.660
[-13. 15. 1.] [-2.39371888 2.76198332 0.18413222] 0.131 0.123 3.660
[-11. -15. 1.] [-2.02545444 -2.76198332 0.18413222] 0.168 0.155 3.430
[-11. 15. 1.] [-2.02545444 2.76198332 0.18413222] 0.168 0.155 3.430
[-8. -4. 0.] [-1.47305777 -0.73652889 0. ] 8.632 2.265 1.647
[-8. 0. 0.] [-1.47305777 0. 0. ] 12.008 2.566 1.473
[-8. 4. 0.] [-1.47305777 0.73652889 0. ] 8.632 2.265 1.647
[-6. -6. 0.] [-1.10479333 -1.10479333 0. ] 10.107 2.408 1.562
[-6. -2. 0.] [-1.10479333 -0.36826444 0. ] 23.163 3.185 1.165
[-6. 2. 0.] [-1.10479333 0.36826444 0. ] 23.163 3.185 1.165
[-6. 6. 0.] [-1.10479333 1.10479333 0. ] 10.107 2.408 1.562
[-4. -8. 0.] [-0.73652889 -1.47305777 0. ] 8.632 2.265 1.647
[-4. -4. 0.] [-0.73652889 -0.73652889 0. ] 31.489 3.481 1.042
[-4. 0. 0.] [-0.73652889 0. 0. ] 84.041 4.443 0.737
[-4. 4. 0.] [-0.73652889 0.73652889 0. ] 31.489 3.481 1.042
[-4. 8. 0.] [-0.73652889 1.47305777 0. ] 8.632 2.265 1.647
[-2. -6. 0.] [-0.36826444 -1.10479333 0. ] 23.163 3.185 1.165
[-2. -2. 0.] [-0.36826444 -0.36826444 0. ] 221.914 5.407 0.521
[-2. 2. 0.] [-0.36826444 0.36826444 0. ] 221.914 5.407 0.521
[-2. 6. 0.] [-0.36826444 1.10479333 0. ] 23.163 3.185 1.165
[ 0. -8. 0.] [ 0. -1.47305777 0. ] 12.008 2.566 1.473
[ 0. -4. 0.] [ 0. -0.73652889 0. ] 84.041 4.443 0.737
[0. 4. 0.] [0. 0.73652889 0. ] 84.041 4.443 0.737
[0. 8. 0.] [0. 1.47305777 0. ] 12.008 2.566 1.473
[ 2. -6. 0.] [ 0.36826444 -1.10479333 0. ] 23.163 3.185 1.165
[ 2. -2. 0.] [ 0.36826444 -0.36826444 0. ] 221.914 5.407 0.521
[2. 2. 0.] [0.36826444 0.36826444 0. ] 221.914 5.407 0.521
[2. 6. 0.] [0.36826444 1.10479333 0. ] 23.163 3.185 1.165
[ 4. -8. 0.] [ 0.73652889 -1.47305777 0. ] 8.632 2.265 1.647
[ 4. -4. 0.] [ 0.73652889 -0.73652889 0. ] 31.489 3.481 1.042
[4. 0. 0.] [0.73652889 0. 0. ] 84.041 4.443 0.737
[4. 4. 0.] [0.73652889 0.73652889 0. ] 31.489 3.481 1.042
[4. 8. 0.] [0.73652889 1.47305777 0. ] 8.632 2.265 1.647
[ 6. -6. 0.] [ 1.10479333 -1.10479333 0. ] 10.107 2.408 1.562
[ 6. -2. 0.] [ 1.10479333 -0.36826444 0. ] 23.163 3.185 1.165
[6. 2. 0.] [1.10479333 0.36826444 0. ] 23.163 3.185 1.165
[6. 6. 0.] [1.10479333 1.10479333 0. ] 10.107 2.408 1.562
[ 8. -4. 0.] [ 1.47305777 -0.73652889 0. ] 8.632 2.265 1.647
[8. 0. 0.] [1.47305777 0. 0. ] 12.008 2.566 1.473
[8. 4. 0.] [1.47305777 0.73652889 0. ] 8.632 2.265 1.647
[ 11. -15. 1.] [ 2.02545444 -2.76198332 0.18413222] 0.168 0.155 3.430
[11. 15. 1.] [2.02545444 2.76198332 0.18413222] 0.168 0.155 3.430
[ 13. -15. 1.] [ 2.39371888 -2.76198332 0.18413222] 0.131 0.123 3.660
[13. 15. 1.] [2.39371888 2.76198332 0.18413222] 0.131 0.123 3.660
[ 15. -15. 1.] [ 2.76198332 -2.76198332 0.18413222] 0.101 0.097 3.910
[ 15. -13. 1.] [ 2.76198332 -2.39371888 0.18413222] 0.131 0.123 3.660
[ 15. -11. 1.] [ 2.76198332 -2.02545444 0.18413222] 0.168 0.155 3.430
[15. 11. 1.] [2.76198332 2.02545444 0.18413222] 0.168 0.155 3.430
[15. 13. 1.] [2.76198332 2.39371888 0.18413222] 0.131 0.123 3.660
[15. 15. 1.] [2.76198332 2.76198332 0.18413222] 0.101 0.097 3.910
Calculating Kikuchi lines for zone: [0. 0. 1.]
done
5.5.7. Comparison#
Comparison between experimental pattern and kinematic theory
Experimental Bragg reflection in polar coordinates
print('distance [pixel] angle [degree] ')
for spot in close_spots:
print(f'{np.linalg.norm(spot):8.3f} \t {np.degrees(np.arctan2(spot[0], spot[1])):5.1f} ' )
distance [pixel] angle [degree]
336.784 75.3
336.300 -104.7
360.840 165.6
360.716 -14.3
492.756 122.5
496.333 -151.6
496.095 28.4
493.178 -57.6
Select the largest g distance that you want to have indexed.
# ----- Input ------
max_g_length = 1.
# ------------------
allowed_g = atoms.info['diffraction']['allowed']['g']
allowed_hkl = atoms.info['diffraction']['allowed']['hkl']
close = np.where(np.linalg.norm(allowed_g[:, :2], axis=1)<max_g_length)
smallest_reciprocal_length = np.min(np.linalg.norm(allowed_g[:, :2], axis=1))
print(f' Smallest reciprocal length is {smallest_reciprocal_length:.3f} 1/Ang')
print()
print(' hkl coordinates lengths in 1/Ang\n')
for index in close[0]:
print(allowed_hkl[index], '\t', np.round(allowed_g[index], 3), '\t',
np.linalg.norm(allowed_g[index]))
print(smallest_reciprocal_length )
Smallest reciprocal length is 0.521 1/Ang
hkl coordinates lengths in 1/Ang
[-4. 0. 0.] [-0.737 0. 0. ] 0.7365288866629349
[-2. -2. 0.] [-0.368 -0.368 0. ] 0.5208045702991394
[-2. 2. 0.] [-0.368 0.368 0. ] 0.5208045702991394
[ 0. -4. 0.] [ 0. -0.737 0. ] 0.7365288866629349
[0. 4. 0.] [0. 0.737 0. ] 0.7365288866629349
[ 2. -2. 0.] [ 0.368 -0.368 0. ] 0.5208045702991394
[2. 2. 0.] [0.368 0.368 0. ] 0.5208045702991394
[4. 0. 0.] [0.737 0. 0. ] 0.7365288866629349
0.5208045702991394
Enter the distance from center for one of the closest experimental Bragg reflections in pixel with assoicated angle
# -------Input of grain size ----
first_peak_length_in_pixel = 336.78377
rotation_angle = 75.29323
# degrees
# -------------------------------
first_peak_reciprocal_distance = np.min(np.linalg.norm(allowed_g[:,:2], axis=1))
pixel_size = first_peak_reciprocal_distance/first_peak_length_in_pixel
closest_sim = np.argmin(np.linalg.norm(allowed_g[:,:2], axis=1))
angle_closest_reflection = np.degrees(np.arctan2(allowed_g[closest_sim,1], allowed_g[closest_sim,0]))
rotation_angle = rotation_angle - angle_closest_reflection
tags_simulation = atoms.info['diffraction']
scaled_extent= extent*pixel_size
angle = np.radians(rotation_angle)
c = np.cos(angle)
s = np.sin(angle)
r_mat = np.array([[c,-s,0],[s,c,0],[0,0,1]])
rmat_g= r_mat
spots_experiment_scaled = spots_experiment*pixel_size
spots_simulation = np.dot(allowed_g, r_mat)
spots_ZOLZ = spots_simulation[atoms.info['diffraction']['allowed']['ZOLZ']]
fig = plt.figure()
fig.suptitle(material+' SAED in ' + str( atoms.info['experimental']['zone_hkl']), fontsize=20)
plt.scatter(spots_experiment_scaled[:,0], spots_experiment_scaled[:,1], c='blue', alpha = 0.5, label='experiment')
plt.scatter(spots_simulation[:,0], spots_simulation[:,1], c='red', alpha = 0.2, label='simulation')
plt.imshow(np.log2(1+diff_pattern), cmap="gray", extent=scaled_extent, vmin=np.max(np.log2(1 + diff_pattern)) * 0.5)
for i in range(len(spots_simulation)):
if np.linalg.norm(spots_simulation[i]) < max_g_length:
plt.text(spots_simulation[i,0], spots_simulation[i,1],str(tags_simulation['allowed']['hkl'][i]),
fontsize = 8, horizontalalignment = 'center', verticalalignment ='bottom')
plt.legend()
[-4. 0. 0.]
[-2. -2. 0.]
[-2. 2. 0.]
[ 0. -4. 0.]
[0. 4. 0.]
[ 2. -2. 0.]
[2. 2. 0.]
[4. 0. 0.]
<matplotlib.legend.Legend at 0x1e700bfd730>
5.5.8. Homework#
Index the diffraction pattern for two different zone axes.
Submit two notebooks each with a diffraction pattern of a different zone axis
Optional:
Plot the indicated camera length over the pixel size!
for i in range(len(spots_simulation)):
if np.linalg.norm(spots_simulation[1]) <1:
print(tags_simulation['allowed']['hkl'][i])